//
//  ImageDownloader.m
//  pa
//
//  Created by HaiJiao Chen on 12-8-8.
//  Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
//

#import "ImageDownloader.h"
#import <CommonCrypto/CommonDigest.h>
#import "LoginServer.h"

NSString* ImageDownloaderNotification = @"ImageDownloaderNotification";

static ImageDownloader* ImageDownloader_sharedInstance = nil;
@implementation ImageDownloader

- (id)init
{
    self = [super init];
    if (self)
    {
        need_to_download = [[NSMutableArray alloc] initWithCapacity:10];
        downloaders = [[NSMutableDictionary alloc] initWithCapacity:10];
        
        //NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
        diskCachePath = [[NSTemporaryDirectory() stringByAppendingPathComponent:@"ImageCache"] retain];
        
        if (![[NSFileManager defaultManager] fileExistsAtPath:diskCachePath])
        {
            [[NSFileManager defaultManager] createDirectoryAtPath:diskCachePath
                                      withIntermediateDirectories:YES
                                                       attributes:nil
                                                            error:NULL];
        }
    }
    return self;
}

- (void)dealloc
{
    [need_to_download release];
    [downloaders release];
    [diskCachePath release];
    [super dealloc];
}

- (NSString *)cachePathForKey:(NSString *)key
{
    const char *str = [key UTF8String];
    unsigned char r[CC_MD5_DIGEST_LENGTH];
    CC_MD5(str, (CC_LONG)strlen(str), r);
    NSString *filename = [NSString stringWithFormat:@"_%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
                          r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9], r[10], r[11], r[12], r[13], r[14], r[15]];
    
    return [diskCachePath stringByAppendingPathComponent:filename];
}

- (UIImage*)downloadImage:(NSString*)uri
{
    if (uri)
    {
        UIImage *image = [[[UIImage alloc] initWithContentsOfFile:[self cachePathForKey:uri]] autorelease];
        if (image == nil)
        {
            if ([need_to_download count] == 0)
            {
                if ([downloaders valueForKey:uri] == nil)
                {
                    NSArray* servers = [LoginServer sharedInstance].data;
                    NSMutableArray* arr = [[NSMutableArray alloc] initWithCapacity:10];
                    for (int i = 0; i < [servers count]; i++)
                    {
                        NSMutableDictionary* dic = [servers objectAtIndex:i];
                        NSString* server = [dic valueForKey:@"url"];
                        NSRange schame = [server rangeOfString:@"://"];
                        if (schame.location != NSNotFound)
                        {
                            NSRange range = [server rangeOfString:@"/" options:NSLiteralSearch range:NSMakeRange(schame.location+3, server.length - schame.location - 3)];
                            if (range.location != NSNotFound)
                            {
                                server = [server substringToIndex:range.location];
                            }
                        }
                        
                        NSMutableURLRequest* request = [[NSMutableURLRequest alloc] init];
                        [request setURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/%@", server, uri]]];
                        [request setTimeoutInterval:10];
                        [request setHTTPMethod:@"GET"];
                        
                        NSURLConnection* connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
                        [request release];
                        
                        NSMutableData* data = [[NSMutableData alloc] initWithCapacity:100];
                        if ([[dic valueForKey:@"connected"] boolValue])
                        {
                            [arr insertObject:[NSArray arrayWithObjects:data, connection, server, nil] atIndex:0];
                        }
                        else
                        {
                            [arr addObject:[NSArray arrayWithObjects:data, connection, server, nil]];
                        }
                        [connection release];
                        [data release];
                    }
                    
                    [downloaders setValue:arr forKey:uri];
                    
                    NSURLConnection* connection = [[arr objectAtIndex:0] objectAtIndex:1];
                    [connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
                    [connection start];
                    
                    [arr release];
                }
            }
            else
            {
                [need_to_download removeObject:uri];
                [need_to_download addObject:uri];
            }
        }
        return image;
    }
    return nil;
}

- (NSString*)getConnectionUri:(NSURLConnection*)aConnection
{
    NSArray* allkeys = downloaders.allKeys;
    for (NSString* key in allkeys)
    {
        NSArray* temp = [downloaders objectForKey:key];
        for (NSArray* arr in temp)
        {
            if ([arr objectAtIndex:1] == aConnection)
            {
                return key;
            }
        }
    }
    return nil;
}

- (NSMutableData*)getConnectionBuffer:(NSURLConnection*)aConnection
{
    NSArray* allkeys = downloaders.allKeys;
    for (NSString* key in allkeys)
    {
        NSArray* temp = [downloaders objectForKey:key];
        for (NSArray* arr in temp)
        {
            if ([arr objectAtIndex:1] == aConnection)
            {
                return [arr objectAtIndex:0];
            }
        }
    }
    return nil;
}

-(void)continueQueue
{
    if ([need_to_download count] > 0)
    {
        NSString* address = [[need_to_download objectAtIndex:0] retain];
        [need_to_download removeObjectAtIndex:0];
        [self downloadImage:address];
        [address release];
    }
}
#pragma mark NSURLConnection (delegate)

- (void)connection:(NSURLConnection *)aConnection didReceiveData:(NSData *)data
{
    [[self getConnectionBuffer:aConnection] appendData:data];
}

#pragma GCC diagnostic ignored "-Wundeclared-selector"
- (void)connectionDidFinishLoading:(NSURLConnection *)aConnection
{
    NSData* data = [self getConnectionBuffer:aConnection];
    NSString* uri = [self getConnectionUri:aConnection];
    
    [data writeToFile:[self cachePathForKey:uri] atomically:YES];
    
    [[NSNotificationCenter defaultCenter] postNotificationName:ImageDownloaderNotification object:uri];
    
    NSArray* temp = [downloaders objectForKey:uri];
    for (NSArray* arr in temp)
    {
        NSURLConnection* connection = [arr objectAtIndex:1];
        [connection cancel];
    }
    [downloaders removeObjectForKey:uri];
    
    [self continueQueue];
}

- (void)connection:(NSURLConnection *)aConnection didFailWithError:(NSError *)error
{
    NSString* uri = [self getConnectionUri:aConnection];
    NSMutableArray* temp = [downloaders objectForKey:uri];
    for (int i = 0; i < [temp count]; i++)
    {
        NSArray* arr = [temp objectAtIndex:i];
        if ([arr objectAtIndex:1] == aConnection)
        {
            [temp removeObjectAtIndex:i];
            break;
        }
    }
    
    if (temp.count == 0)
    {
        [downloaders removeObjectForKey:uri];
        [self continueQueue];
    }
    else
    {
        NSURLConnection* connection = [[temp objectAtIndex:0] objectAtIndex:1];
        [connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        [connection start];
    }
}


+ (ImageDownloader*)sharedInstance
{
    if (ImageDownloader_sharedInstance == nil)
    {
        ImageDownloader_sharedInstance = [[ImageDownloader alloc] init];
    }
    return ImageDownloader_sharedInstance;
}


@end
